import { useEffect, useRef, useState } from 'react'
import './ImageExportModal.scss'
import RemoveSvg from '@/svg/RemoveSvg'
import useStateRef from '@/hooks/useStateRef'
import imageLoadManager from '@/lib/imageLoadManager'
import { loadImageInfo } from '@/utils/loadVideo'
import { showLoading } from '@/utils/loading'
import useNumInput from '@/hooks/useNumInput'
import CustomCanvas from '@/component/CustomCanvas'
import { showToast } from '@/utils/toast'
import * as dialog from '@tauri-apps/plugin-dialog'
import { canvasToBlob, dateFormat } from '@/utils/common'
import JSZip from 'jszip'
import { invoke } from '@tauri-apps/api/core'
import { useI18n } from '@/i18n'
interface Props {
  show: boolean
  onHide: () => void
  frameList: FrameInfo[]
  allFrameList: FrameInfo[]
  fps: number
}

const imageFmtList = [
  {
    name: 'WEBP',
    ext: 'webp',
    mime: 'image/webp',
  },
  {
    name: 'PNG',
    ext: 'png',
    mime: 'image/png',
  },
  {
    name: 'JPEG',
    ext: 'jpeg',
    mime: 'image/jpeg',
  },
]

const ImageExportModal = ({
  show,
  onHide,
  frameList,
  allFrameList,
  fps,
}: Props) => {
  const { t } = useI18n()
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const imageFrameList = useRef<HTMLImageElement[]>([])
  const canvasCtx = useRef<CanvasRenderingContext2D | null>(null)
  const [canvasSize, setCanvasSize, canvasSizeRef] = useStateRef({
    width: 200,
    height: 200,
  })
  const [selecImgFmt, onChangeSelecImgFmt] = useState(imageFmtList[0].name)
  const [quality, onChangeQuality, qualityStr, onQualityBlur] = useNumInput(
    0.92,
    {
      int: false,
      min: 0,
      max: 1,
    }
  )

  useEffect(() => {
    const task = async () => {
      if (frameList.length != 0) {
        const info = await loadImageInfo(frameList[0].url)
        setCanvasSize({
          width: info.width,
          height: info.height,
        })
        canvasRef.current.width = info.width
        canvasRef.current.height = info.height
      } else {
        setCanvasSize({ width: 200, height: 200 })
        canvasRef.current.width = 200
        canvasRef.current.height = 200
      }
    }
    task()
  }, [frameList])
  useEffect(() => {
    if (!show) {
      return
    }
    let isEnd = false
    const task = async () => {
      imageFrameList.current = await imageLoadManager.loadImageList(frameList)
      //   if (!play) {
      //     return
      //   }
      // 帧时间
      const frameTime = 1000 / fps
      let frame = 0
      let nowframeTime = 0
      let lastTime = 0
      canvasCtx.current = canvasRef.current.getContext('2d')
      canvasCtx.current.imageSmoothingEnabled = false
      const anim = (nowTime: number) => {
        const deltaTime = nowTime - lastTime
        lastTime = nowTime
        nowframeTime += deltaTime
        const addFrame = Math.floor(nowframeTime / frameTime)
        nowframeTime = nowframeTime % frameTime
        draw(frame)
        frame += addFrame
        if (frameList.length == 0) isEnd = true
        while (frame >= frameList.length && frameList.length != 0) {
          frame -= frameList.length
        }
        if (isEnd) return
        requestAnimationFrame(anim)
      }
      requestAnimationFrame(anim)
    }
    task()
    return () => {
      isEnd = true
    }
  }, [show, frameList, canvasSize])

  const draw = (frame = 0) => {
    if (frame < 0 || frame >= imageFrameList.current.length) {
      return
    }
    const ctx = canvasCtx.current
    if (!ctx) return
    const w = canvasSizeRef.current.width
    const h = canvasSizeRef.current.height
    ctx.clearRect(0, 0, w, h)
    if (frameList.length == 0) {
      return
    }
    const imageW = imageFrameList.current[frame].naturalWidth
    const imageH = imageFrameList.current[frame].naturalHeight
    ctx.drawImage(
      imageFrameList.current[frame],
      0,
      0,
      imageW,
      imageH,
      0,
      0,
      w,
      h
    )
  }

  async function onSaveZip(): Promise<void> {
    const hideloading = showLoading(t('exporting'))
    try {
      const fmt = imageFmtList.find((item) => item.name == selecImgFmt)
      let path = null
      path = await dialog.save({
        canCreateDirectories: true,
        title: t('exportImageCollection'),
        defaultPath: dateFormat(new Date(), 'MM_dd_hh_mm_ss_images') + '.zip',
        filters: [
          {
            name: 'ZIP',
            extensions: ['zip'],
          },
        ],
      })
      // dialog.open({
      //   directory: true,
      //   multiple: false,
      //   title: '选择导出目录',
      //   canCreateDirectories: true,
      // })

      if (!path) return
      const canvas = document.createElement('canvas')
      const w = imageFrameList.current[0].naturalWidth
      const h = imageFrameList.current[0].naturalHeight
      canvas.width = w
      canvas.height = h
      const ctx = canvas.getContext('2d')
      if (!ctx) return
      // const fileList: File[] = []
      const zip = new JSZip()

      for (let i = 0; i < frameList.length; i++) {
        ctx.clearRect(0, 0, w, h)
        const frame = imageFrameList.current[i]
        ctx.drawImage(
          frame,
          0,
          0,
          imageFrameList.current[i].naturalWidth,
          imageFrameList.current[i].naturalHeight,
          0,
          0,
          w,
          h
        )
        const blob = await canvasToBlob(canvas, fmt.mime, quality)
        // const file = new File([blob], `${i + 1}.${fmt.ext}`)
        // fileList.push(file)
        zip.file(`${i + 1}.${fmt.ext}`, blob)
      }
      const data = await zip.generateAsync({ type: 'blob' })
      await invoke('save_file_to_path', {
        buffer: await data.arrayBuffer(),
        path,
      })
      showToast(t('exportSuccessful'))
    } catch (e) {
      console.error(e)
      showToast(t('exportFailed'))
    } finally {
      hideloading()
    }
  }
  async function onSaveFolder(): Promise<void> {
    const hideloading = showLoading('导出中')
    try {
      const fmt = imageFmtList.find((item) => item.name == selecImgFmt)
      let path = null
      // path = await dialog.save({
      //   canCreateDirectories: true,
      //   title: '导出图片集合',
      //   defaultPath:
      //     dateFormat(new Date(), 'MM月dd日 hh_mm_ss_images') + '.zip',
      //   filters: [
      //     {
      //       name: 'ZIP',
      //       extensions: ['zip'],
      //     },
      //   ],
      // })
      path = await dialog.open({
        directory: true,
        multiple: false,
        title: '选择导出目录',
        canCreateDirectories: true,
      })

      if (!path) return
      const canvas = document.createElement('canvas')
      const w = imageFrameList.current[0].naturalWidth
      const h = imageFrameList.current[0].naturalHeight
      canvas.width = w
      canvas.height = h
      const ctx = canvas.getContext('2d')
      if (!ctx) return
      const fileList: File[] = []
      for (let i = 0; i < frameList.length; i++) {
        ctx.clearRect(0, 0, w, h)
        const frame = imageFrameList.current[i]
        ctx.drawImage(
          frame,
          0,
          0,
          imageFrameList.current[i].naturalWidth,
          imageFrameList.current[i].naturalHeight,
          0,
          0,
          w,
          h
        )
        const blob = await canvasToBlob(canvas, fmt.mime, quality)
        const file = new File([blob], `${i + 1}.${fmt.ext}`)
        fileList.push(file)
        // zip.file(`${i + 1}.${fmt.ext}`, blob)
      }
      // const data = await zip.generateAsync({ type: 'blob' })
      for (let i = 0; i < fileList.length; i++) {
        await invoke('save_file_to_path', {
          buffer: await fileList[i].arrayBuffer(),
          path: `${path}/${fileList[i].name}`,
        })
      }
      showToast(t('exportSuccessful'))
    } catch (e) {
      console.error(e)
      showToast(t('exportFailed'))
    } finally {
      hideloading()
    }
  }

  return (
    <div className="ImageExportModal-component">
      <div className={`ImageExportModal ${show ? 'show' : ''}`}>
        <div className="top">
          <div className="title">
            <span>{t('exportImageCollection')}</span>
          </div>
          <ripple-button className="remove" onClick={onHide}>
            <RemoveSvg />
          </ripple-button>
        </div>
        <div className="center-box">
          <div className="canvas-view">
            <CustomCanvas className="canvas" ref={canvasRef}></CustomCanvas>
          </div>
          <div className="input-box">
            <div className="label">
              <label>{t('exportFormat')}</label>
            </div>
            <select
              className="select"
              value={selecImgFmt}
              onChange={(e) => {
                onChangeSelecImgFmt(e.target.value)
              }}>
              {imageFmtList.map((item) => {
                return (
                  <option key={item.name} value={item.name}>
                    {item.name}
                  </option>
                )
              })}
            </select>
          </div>

          <div className="input-box" style={{ height: 30 }}>
            {selecImgFmt !== 'PNG' && (
              <>
                <div className="label">
                  <label>{t('imageQuality')}</label>
                </div>
                <div
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: 5,
                  }}>
                  <input
                    type="range"
                    style={{
                      width: 115,
                    }}
                    onChange={(e) => {
                      onChangeQuality(e.target.value)
                    }}
                    step={0.01}
                    min={0}
                    max={1}
                    value={quality}></input>
                  {/* {power} */}
                  <input
                    type="number"
                    style={{
                      width: 60,
                    }}
                    className="input"
                    value={qualityStr}
                    onChange={(e) => onChangeQuality(e.target.value)}
                    onBlur={onQualityBlur}
                  />
                </div>
              </>
            )}
          </div>
        </div>
        <div
          style={{
            justifyContent: 'flex-end',
            display: 'flex',
            alignItems: 'center',
            gap: 10,
            marginTop: 12,
          }}>
          <ripple-button
            style={{
              marginLeft: 'auto',
              background: 'var(--primary-color)',
              color: 'white',
              width: 100,
              padding: '8px 0',
            }}
            onClick={onSaveZip}>
            {t('exportZip')}
          </ripple-button>
          <ripple-button
            style={{
              background: 'var(--primary-color)',
              color: 'white',
              width: 130,
              padding: '8px 0',
            }}
            onClick={onSaveFolder}>
            {t('exportToFolder')}
          </ripple-button>
        </div>
      </div>
      <div className={`mask ${show ? 'show' : ''}`} onClick={onHide}></div>
    </div>
  )
}

export default ImageExportModal
